﻿#pragma once
#include "yzrutil.h"
#include <atomic>

namespace yzrilyzr_util{
	EBCLASS(Random){
	private:
	static constexpr int64_t multiplier=0x5DEECE66D;
	static constexpr int64_t addend=0xB;
	static constexpr int64_t mask=((int64_t)1 << 48) - 1;
	static constexpr double DOUBLE_UNIT=0x1.0p-53; // 1.0 / (1L << Double.PRECISION)
	static constexpr float FLOAT_UNIT=0x1.0p-24f; // 1.0f / (1 << Float.PRECISION)
	std::atomic<int64_t> seed;
	double nextNextGaussian=0.0;
	bool haveNextNextGaussian=false;
	//
	static int64_t initialScramble(int64_t seed);
	static int64_t seedUniquifier();

	public:
	Random();
	Random(int64_t seed);
	double nextGaussian();
	int32_t nextInt();
	int32_t nextInt(int32_t bound);
	bool nextBoolean();
	int64_t nextLong();
	double nextDouble();
	float nextFloat();
	protected:
	int32_t next(int32_t bits);
	};
}
